require 'rexml/document'
require 'c:/tools/kronos/ruby/state'

class Line

  attr_accessor :event
  attr_accessor :actions
  attr_accessor :start_nameU
  attr_accessor :start_name
  attr_accessor :end_nameU
  attr_accessor :end_name
	attr_accessor :merge_actions

  def initialize( xml_doc )

		if nil != xml_doc 
			@start_nameU = xml_doc.elements["XForm1D"].elements["BeginX"].attributes["F"]
			@end_nameU   = xml_doc.elements["XForm1D"].elements["EndX"].attributes["F"]
		end

		@merge_actions = Hash.new

		if nil != xml_doc 
			text_str = String.new

			xml_doc.elements["Text"].texts.each { |text_node|
				text_str << text_node.value
			}

			setEventsAndActions text_str
			
			if ( :FAIL == stripStart ) or ( :FAIL == stripEnd )
				puts "FAILED VISIO CONNECTION: #{@event}, #{@actions.inspect}"
			end

		end

  end

  def setEventsAndActions( payload )

    if nil != payload

			# TODO: Use strip to get rid of \n after the 
			# string is seperated into individual characters
      position = payload.index "\\"

      if ( nil != position ) # event
        @event = payload.slice!(0..(position - 1)).chomp
        payload.slice!(0..1)
        @actions = payload.split "\n"
      else # merge
        @actions = payload.split "\n"
      end

    end

  end

  def stripStart

    begin
      position = @start_nameU.index '\''
      if nil != position
        @start_nameU.slice!(0..position)
      else
        return :FAIL
      end

      position = @start_nameU.index '\''
      if nil != position
        @start_nameU = @start_nameU.slice!(0..(position - 1))
      else
        return :FAIL
      end

      return :PASS
      
    rescue
      raise "YOU SUCK: #{self.inspect}"
    end


    
  end

  def stripEnd

    begin
      position = @end_nameU.index '\''
      @end_nameU.slice!(0..position)
    rescue
      raise "YOU SUCK: #{self.inspect}"
    end

    position = @end_nameU.index '\''
    @end_nameU = @end_nameU.slice!(0..(position - 1))
    
  end

  def consolidateLineNames( states, lines )

    @start_name = @start_nameU
    @end_name   = @end_nameU

		# Try to catch a state match
    states.each { |state|
      if @start_nameU == state.nameU
        @start_name = state.name
      end
      
      if @end_nameU == state.nameU
        @end_name = state.name
      end
    }

  end

	def consolidateMerging( states, lines )

		if nil == end_nameU.index("State") and nil != start_nameU.index("State")
			@merge_actions = Line.recursiveMergeConsolidation( self, states, lines )
		else
			@merge_actions = nil
		end

	end

	def self.recursiveMergeConsolidation( line_obj, states, lines )

		temp_merge_hash = Hash.new

		temp_merge_hash[:guard]             = nil
		temp_merge_hash[:guard_actions]     = nil
		temp_merge_hash[:guard_destination] = nil
		temp_merge_hash[:guard_branch]      = nil
		temp_merge_hash[:else_guard]        = nil
		temp_merge_hash[:else_actions]      = nil
		temp_merge_hash[:else_destination]  = nil
		temp_merge_hash[:else_branch]       = nil
		temp_merge_hash[:actions]     			= nil
		temp_merge_hash[:destination] 			= nil
		temp_merge_hash[:recurse]           = nil
		temp_merge_hash[:branch]						= nil

		temp_merge_hash[:recurse] = FALSE
		temp_merge_hash[:guard_recurse] = FALSE
		temp_merge_hash[:else_recurse] = FALSE

		# Cycle through lines for matching
		lines.each { | line |

			if line_obj.end_nameU == line.start_nameU

				# if it is a decision
				if nil != line.event

					# Format Decision statement
					start_strip = line.event.index("[")
					stop_strip  = line.event.index("]")

					if nil != stop_strip
						stop_strip = stop_strip - 1
					end

					if nil != start_strip
						start_strip = start_strip + 1
					end

					if nil != stop_strip and nil != start_strip
						line.event   = line.event[start_strip..stop_strip]
					end

					# Filter decision for else statement
					if "else" != line.event
						temp_merge_hash[:guard] = line.event
						temp_merge_hash[:guard_actions] = line.actions.clone

						if nil != line.end_nameU.index("State")
							temp_merge_hash[:guard_recurse] = FALSE
							temp_merge_hash[:guard_destination] = line.end_name.chomp.clone
							temp_merge_hash[:guard_branch] = nil
						else
							# Enter recursive method, until all tree data is determined
							temp_merge_hash[:guard_recurse] = TRUE
							temp_merge_hash[:guard_destination] = nil
							temp_merge_hash[:guard_branch] = Hash.new
							temp_merge_hash[:guard_branch] = recursiveMergeConsolidation( line, states, lines )

						end

					else
						temp_merge_hash[:else_guard] = line.event
						temp_merge_hash[:else_actions] = line.actions.clone

						if nil != line.end_nameU.index("State")
							temp_merge_hash[:else_recurse] = FALSE
							temp_merge_hash[:else_destination] = line.end_name.chomp.clone
							temp_merge_hash[:else_branch] = nil
						else
							# Enter recursive method, until all tree data is determined
							temp_merge_hash[:else_recurse] = TRUE
							temp_merge_hash[:else_destination] = nil
							temp_merge_hash[:else_branch] = Hash.new
							temp_merge_hash[:else_branch] = recursiveMergeConsolidation( line, states, lines )
						end

					end

				else # Merge

					temp_merge_hash[:actions] = line.actions
					if nil != line.end_nameU.index("State")
						temp_merge_hash[:recurse] = FALSE
						temp_merge_hash[:destination] = line.end_name.chomp
						temp_merge_hash[:branch] = nil
					else
						temp_merge_hash[:recurse] = TRUE
						temp_merge_hash[:destination] = nil
						temp_merge_hash[:branch] = Hash.new
						temp_merge_hash[:branch] = recursiveMergeConsolidation( line, states, lines )
					end

				end

			end

		}

		return temp_merge_hash

	end

end

